﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.Threading;
using Foundation;

namespace RPGSoundmixer {
    public class KeyHandler {
        private Form1 form;
        private AxWMPLib.AxWindowsMediaPlayer player1;
        private AxWMPLib.AxWindowsMediaPlayer player2;        
        private EffektGroup currentCategorie;
        private Effekt currentSound;
        private Effekt currentEffect; 

        public CategorieCollection CategorieCollection { get; set; }
        


        
        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="xmlFilePath"></param>
        /// <param name="form"></param>
        public KeyHandler(Form1 form) {
            this.CategorieCollection = CategorieCollection.GetInstance();
            //loadSoundEffekts();
            //this.createSampleEffect();
            this.form = form;                    
            this.player1 = form.Player1;
            this.player2 = form.Player2;
            this.player1.PlayStateChange += new AxWMPLib._WMPOCXEvents_PlayStateChangeEventHandler(player1_PlayStateChange);
            this.player2.PlayStateChange += new AxWMPLib._WMPOCXEvents_PlayStateChangeEventHandler(player2_PlayStateChange);
        }

        void player2_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e) {

            //if (e.newState == 1) {
            //    player2.Ctlcontrols.stop();
            //    if (currentEffect.followingEffect != null) {
            //        this.processEffect(currentEffect.followingEffect);
            //    }
            //}
        }

        private void loadSoundEffekts() {
            throw new NotImplementedException();
        }

        void player1_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e) {
            if (player1.currentMedia != null) {
                this.form.setTitleName(player1.currentMedia.name);
            }
        }

        
        /// <summary>
        /// Führt die Aktion für den entsprechenden Key aus.
        /// </summary>
        /// <param name="key"></param>
        public void HandleKey(char key) {
            if (key.Equals('§')) {
                this.stopEffects();
            }
            else if (char.IsDigit(key)) {
                changeCategory(key);
            }
            else {
                Effekt outEffekt; 
                if (this.currentCategorie.Effects.TryGetValue(key, out outEffekt)) {
                    processEffect(outEffekt);
                }
            }
        }

        private void stopEffects() {
            this.fadeOutIfNecessary();
        }

        private void processEffect(Effekt effect) {

            switch (effect.Type) {
                case EffektTypeEnum.RandomPlaylist:
                    this.currentSound = effect; 
                    this.playRandomPlaylist();
                    break;
                case EffektTypeEnum.RandomSingleTrack:
                    this.currentSound = effect; 
                    this.playRandomSingleTrack();
                    break;
                case EffektTypeEnum.SingleEffect:
                    this.currentEffect = effect; 
                    this.playSingleEffect();
                    break; 
                default:
                    break;
            }
        }

        private void playSingleEffect() {
            string playlistName = this.currentEffect.Name;
            WMPLib.IWMPPlaylist pl = this.player2.playlistCollection.newPlaylist(playlistName);

            foreach (Track track in this.currentEffect.Tracks) {
                if (File.Exists(track.FullPath)) {
                    pl.appendItem(this.player2.newMedia(track.FullPath));
                }
            }                        
            this.form.Player2.currentPlaylist = pl;
            this.player2.settings.volume = currentEffect.Volume; 
            this.form.Player2.Ctlcontrols.play();
        }
        

        private void playRandomSingleTrack() {
            this.fadeOutIfNecessary();
            Random rnd = new Random();
            int key = rnd.Next(0, currentSound.Tracks.Count());
            this.player1.settings.volume = currentSound.Volume; 
            this.form.Player1.URL = this.currentSound.Tracks.ElementAt(key).FullPath; 
        }

        /// <summary>
        /// Wenn bereits eine Playlist am laufen ist, wird diese ausgeblendet
        /// </summary>
        private void fadeOutIfNecessary() {
            if (this.player1.playState == WMPLib.WMPPlayState.wmppsPlaying) {
                int preVol = this.form.Player1.settings.volume;
                while (this.form.Player1.settings.volume != 0) {
                    this.player1.settings.volume--;
                    Thread.Sleep(50);
                }
                this.player1.Ctlcontrols.stop();
                this.player1.settings.volume = preVol;
            }
        }



        /// <summary>
        /// Spielt eine 
        /// </summary>
        /// <param name="effekt"></param>
        private void playRandomPlaylist() {
            string playlistName = this.currentSound.Name;
            try {
                WMPLib.IWMPPlaylist pl = this.player1.playlistCollection.newPlaylist(playlistName);
                foreach (Track track in this.currentSound.Tracks) {
                    if (File.Exists(track.FullPath)) {
                        pl.appendItem(this.player1.newMedia(track.FullPath));
                    }
                }
                this.fadeOutIfNecessary();
                this.player1.settings.volume = currentSound.Volume;
                this.form.Player1.settings.setMode("shuffle", true);
                this.form.Player1.currentPlaylist = pl;
                this.form.Player1.Ctlcontrols.play();
            }
            catch{
                this.form.setTitleName("Fehler beim Laden der Datei"); 
            }           
        }


        /// <summary>
        /// Gibt eine Liste mit allen Kategorien zurück
        /// </summary>
        /// <returns></returns>
        public string[] GetCategories() {
            List<string> returnList = new List<string>();
            foreach (KeyValuePair<char, EffektGroup> pair in this.CategorieCollection.Categories) {
                returnList.Add(string.Format("{0} - {1}", pair.Key, pair.Value.Name));
            }
            return returnList.ToArray();
        }
        

        /// <summary>
        /// Setzt die geünschte Kategorie als CurrentCategorie und zeigt die Items der Kategorie im GUI an
        /// </summary>
        /// <param name="key"></param>
        private void changeCategory(char key) {
            if (this.CategorieCollection.Categories.TryGetValue(key, out this.currentCategorie)) {
                this.form.showCategorieItems(this.currentCategorie.Effects.Values.ToArray());
            }
        }

        private void playTrack(string path) {
            this.form.Player1.URL = path; 
        }




        
    }
}

